<?php
namespace frontend\modules\Api\controllers;

use common\event\TallyEvent;
use common\models\TallyAccount;
use common\models\TallyRecord;
use common\services\TallyAccountService;
use common\services\TallyPmService;
use common\services\ToolService;
use frontend\modules\Dao\TallyRecordDao;
use Yii;
use yii\base\ExitException;
use yii\base\InvalidConfigException;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
use yii\base\DynamicModel;
use yii\helpers\Json;

/**
 * Class AccountController
 * @package frontend\modules\Api\controllers
 * 账户管理
 */
class AccountController extends ApiController
{
    /**
     * @return array
     * 引入行为验证 过滤授权
     */
    public function behaviors()
    {
        $config = [
            'access' => [
                'class' => AccessControl::className(),
                'denyCallback' => function($rule, $action){
                    return self::failureResponse(100001, '请先登录!',[]);
                },
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                    ]
                ]
            ],
        ];
        return ArrayHelper::merge(parent::behaviors(), $config);
    }

    /**
     * 重载初始化方案
     */
    public function init()
    {
        parent::init();
        // 注册监听事件
        $this->on(TallyEvent::RECORD_LOG_EVENT,['common\models\Tally','recordLog']);
    }

    /**
     * @throws ExitException
     * @notes 获取账本统计数据
     */
    public function actionSummary()
    {
        if(Yii::$app->request->isPost){

            $tallyId = Yii::$app->getRequest()->post('tally_id');

        }else{

            $tallyId = Yii::$app->getRequest()->get('tally_id');

        }
        if(!$tallyId){
            return self::failureResponse(500,'账本Id不能为空');
        }
        // 检查账本权限 是否可读
        $this->checkRolePermission($this->_user['id'],$tallyId,'read');
        $asset = TallyAccountService::sumAll([
            //['=','uid',$this->_user['id']],
            ['>','money',0],
            ['=','tally_id', $tallyId]
        ]);
        $asset = ToolService::moneyFormat($asset); // 总资产
        $debt  = TallyAccountService::sumAll([
            //['=','uid',$this->_user['id']],
            ['<','money',0],
            ['=','tally_id', $tallyId]
        ]);
        $debt = ToolService::moneyFormat(abs($debt)); // 总负债
        $smInfo = [
            'asset_net'=> ToolService::moneyFormat($asset -  $debt) , //净资产
            'asset' => $asset , //资产
            'debt' => $debt , //负债
        ] ;
        return self::successResponse($smInfo);
    }

    /**
     * @throws
     * 账户列表
     */
    public function actionLists()
    {
        $tallyId = Yii::$app->getRequest()->get('tally_id');
        if(!$tallyId){
            return self::failureResponse(500,'账本Id不能为空');
        }

        Yii::$app->db->createCommand("UPDATE tally_account SET sorting = id where sorting = 0 AND tally_id = $tallyId;")->execute();


        $this->checkRolePermission($this->_user['id'],$tallyId,'read');
        $condition = Yii::$app->request->get(); // type 等参数
        $role = TallyPmService::getRole($this->_user['id'],$tallyId);
        if($role == 'pmanger'){
            $condition['accounts'] = TallyPmService::get_accounts($this->_user['id'],$tallyId);
        }
        $list = TallyAccountService::getList($condition);

        return self::successResponse($list);
    }

    /**
     * @throws
     * 增加账户
     */
    public function actionAdd()
    {
        $form = DynamicModel::validateData([
            'title' => Yii::$app->getRequest()->post('title'),
            'tally_id' => Yii::$app->getRequest()->post('tally_id'),
            'uid'   => $this->_user['id'],
            'type'  => Yii::$app->getRequest()->post('type',1),
            'tag'  => Yii::$app->getRequest()->post('tag'),
            'money' => Yii::$app->getRequest()->post('initial_money',0), //新增账户时 初始金额与余额要保持一致
            'initial_money' => Yii::$app->getRequest()->post('initial_money',0),
            'memo'  => Yii::$app->getRequest()->post('memo',''),
        ],[
            [['title','tally_id','type'], 'required'],
            [['title','tag'], 'filter', 'filter' => 'trim'],
            ['title', 'string','min'=> 1,'max'=> 60],
            ['type', 'integer'],
        ]);
        if ($form->hasErrors()) {
            return self::failureResponse(500,current($form->getFirstErrors()));
        }
        // 检查用户操作权限
        $this->checkRolePermission($this->_user['id'],$form->tally_id,'read');
        $result = TallyAccountService::create(ArrayHelper::toArray($form));
        if($result){
            $this->triggerEvents([
                'tally_id' => $form->tally_id,
                'uid'   => $form->uid,
                'type'  => 1,
                'content' => '新增了账户:'.$form->title
            ]);
            Yii::$app->db->createCommand("UPDATE tally_account SET sorting = id where sorting = 0;")->execute();
            return self::successResponse(['id'=>$result]);
        }else{
            return self::failureResponse(500,'新增失败.'.TallyAccountService::getError());
        }
    }

    /**
     * @throws
     * 编辑账户
     */
    public function actionEdit()
    {
        $form = DynamicModel::validateData([
            'id'    => Yii::$app->getRequest()->post('id'),
            'tally_id' => Yii::$app->getRequest()->post('tally_id'),
            'title' => Yii::$app->getRequest()->post('title'),
            'initial_money' => Yii::$app->getRequest()->post('initial_money',null),
            'memo'  => Yii::$app->getRequest()->post('memo',''),
        ],[
            [['title','tally_id','id'], 'required'],
            ['title', 'filter', 'filter' => 'trim'],
            ['title', 'string','min'=> 1,'max'=> 60],
        ]);
        if ($form->hasErrors()) {
            return self::failureResponse(500,current($form->getFirstErrors()));
        }
        if($form->initial_money === null) unset($form->initial_money);
        // 检查用户操作权限
        $this->checkRolePermission($this->_user['id'],$form->tally_id,'write');
        $result = TallyAccountService::update([
            'id'    => $form->id,
            'tally_id'    => $form->tally_id,
        ],ArrayHelper::toArray($form));
        if($result){
            $this->triggerEvents([
                'tally_id' => $form->tally_id,
                'uid'   => $this->_user['id'],
                'type'  => 1,
                'content' => '修改了账户:'.$form->title.';初始金额:'.$form->initial_money
            ]);
            return self::successResponse();
        }else{
            return self::failureResponse(500,'更新失败.'.TallyAccountService::getError());
        }
    }

    /**
     * 账户重新设置新值
     * @throws ExitException
     * @throws InvalidConfigException
     */
    public function actionSetMoney()
    {
        $form = DynamicModel::validateData([
            'id'    => Yii::$app->getRequest()->post('id'),
            'money' => Yii::$app->getRequest()->post('money'),
        ],[
            [['money','id'], 'required'],
        ]);
        if ($form->hasErrors()) {
            return self::failureResponse(500,current($form->getFirstErrors()));
        }
        $tallyId = Yii::$app->getRequest()->post('tally_id');
        if(!$tallyId) {
            return self::failureResponse(500,'账套ID不能为空');
        }
        // 检查账套操作权限
        $this->checkRolePermission($this->_user['id'],$tallyId,'write');
        $result = TallyAccountService::update(['id'=> $form->id],ArrayHelper::toArray($form));
        if($result){
            return self::successResponse();
        }else{
            return self::failureResponse(500,'更新失败.'.TallyAccountService::getError());
        }
    }

    /**
     * @throws
     * 删除账户
     */
    public function actionDel()
    {
        $id = Yii::$app->getRequest()->post('id');
        if(!$id){
            return self::failureResponse(500,'账户Id不能为空');
        }
        // 检查对账本的操作权限
        $tallyId = Yii::$app->getRequest()->post('tally_id');
        $this->checkRolePermission($this->_user['id'],$tallyId,'write');
        $accountInfo = TallyAccount::find()->where(['id'=>$id])->one();
        $result = TallyAccountService::delete([
            'id'    => $id,
            'tally_id' => $tallyId,
//            'uid'   => $this->_user['id']
        ]);
        if($result){
            $this->triggerEvents([
                'tally_id' => $tallyId,
                'uid'   => $this->_user['id'],
                'type'  => 1,
                'content' => '删除了账户:'.$accountInfo['title']
            ]);
            return self::successResponse();
        }else{
            return self::failureResponse(500,'删除失败.'.TallyAccountService::getError());
        }
    }

    /**
     * 获取账户的类别列表
     * @throws
     */
    public function actionTags()
    {
        $result = ToolService::getConfig('DEFAULT_ACCOUNT_TAG');
        return self::successResponse(Json::decode($result,true));
    }

    /**
     * 账套账户的重新核算 返回账本下 每个账户的金额
     * @throws ExitException
     */
    public function actionReCheck()
    {
        $id = Yii::$app->getRequest()->post('tally_id');
        if(!$id){
            return self::failureResponse(500,'账户Id不能为空');
        }
        $this->checkRolePermission($this->_user['id'],$id,'read');
        $result = TallyAccountService::reCheckMoney($id);
        return self::successResponse($result);
    }


    /**
     * @return null
     * @throws ExitException
     * @throws InvalidConfigException
     */
    public function actionAccountsGroup(){
        $tally_id = Yii::$app->getRequest()->get('tally_id');
        if(!$tally_id){
            return self::failureResponse(500,'账户Id不能为空');
        }
        $condition = Yii::$app->getRequest()->get();
        $arr_tip_str = [
            '现金账户'=>0,
            '金融账户'=>1,
            '虚拟账户'=>2,
            '信用账户'=>3,
            '负债账户'=>4,
            '债权账户'=>5,
            '投资账户'=>6,
            '其他账户'=>7,
            '未知账户'=>8,
            ];
        $all_group = json_decode(ToolService::getConfig('DEFAULT_ACCOUNT_TAG'),true);
        $all_group[] = [
            'id'=>9,
            'title'=>'未知账户',
            'img_url'=>'https://static.gongsizhang.com/2023-09-22-650d781fbd5c7.png'
        ];


        foreach ($all_group as &$value){
            $value['money'] = '0.00';
            $value['children'] = [];
        }
        $accountList = TallyAccount::find()
            ->select('*')
            ->andFilterWhere([
                '=','tally_id',$tally_id
            ])->andFilterWhere([
                '<=','created_time',Yii::$app->getRequest()->get('date')
            ])
            ->select('id,initial_money,title,tag');

        if(TallyRecordDao::checkIsHasField($condition,'tag_name')){
            $accountList->andFilterWhere([
                '=','tag',$condition['tag_name']
            ]);
        }


        $accountList = $accountList->asArray()
            ->all();
        $accountIds = array_column($accountList,'id');
        //查询所有账户的总收入
        $records_shouru = TallyRecord::find()
            ->andFilterWhere([
                'in','account_id',$accountIds
            ])->andFilterWhere([
                '=','tally_id',$tally_id
            ])->andFilterWhere([
                '=','type','10'
            ])->andFilterWhere([
                '<=','tally_time',Yii::$app->getRequest()->get('date')
            ])->select('account_id,sum(amount) as amounts')->groupBy('account_id')
            ->asArray()
            ->all();
        $sRecords = [];
        foreach ($records_shouru as $bValue){
            $sRecords[$bValue['account_id']] = $bValue;
        }
        $records_zhichu = TallyRecord::find()
            ->andFilterWhere([
                'in','account_id',$accountIds
            ])->andFilterWhere([
                '=','tally_id',$tally_id
            ])->andFilterWhere([
                '=','type','20'
            ])->andFilterWhere([
                '<=','tally_time',Yii::$app->getRequest()->get('date')
            ])->select('account_id,sum(amount)  as amounts')->groupBy('account_id')
            ->asArray()
            ->all();
        //计算转账的支出
        $zRecords = [];
        foreach ($records_zhichu as $bValue){
            $zRecords[$bValue['account_id']] = $bValue;
        }
        $zz_records = TallyRecord::find()
            ->andFilterWhere([
                'in','account_id',$accountIds
            ])->andFilterWhere([
                '=','tally_id',$tally_id
            ])->andFilterWhere([
                '=','type','30'
            ])->andFilterWhere([
                '<=','tally_time',Yii::$app->getRequest()->get('date')
            ])->select('account_id,sum(amount)  as amounts')
            ->groupBy('account_id')
            ->asArray()
            ->all();
        $zzRecords = [];
        foreach ($zz_records as $bValue){
            $zzRecords[$bValue['account_id']] = $bValue;
        }
        $zzs_records = TallyRecord::find()
            ->andFilterWhere([
                'in','account_dst_id',$accountIds
            ])->andFilterWhere([
                '=','tally_id',$tally_id
            ])->andFilterWhere([
                '=','type','30'
            ])->andFilterWhere([
                '<=','tally_time',Yii::$app->getRequest()->get('date')
            ])->select('account_dst_id,sum(amount)  as amounts')
            ->groupBy('account_dst_id')
            ->asArray()
            ->all();
        $zzsRecords = [];
        foreach ($zzs_records as $bValue){
            $zzsRecords[$bValue['account_dst_id']] = $bValue;
        }
        foreach ($accountList as &$value){
            $zMoney = 0;
            $sMoney = 0;
            if(isset($sRecords[$value['id']])){
                $sMoney = $sRecords[$value['id']]['amounts'];
            }
            if(isset($zRecords[$value['id']])){
                $zMoney = $zRecords[$value['id']]['amounts'];
            }
            if(isset($zzRecords[$value['id']])){
                $sMoney = bcadd($zzsRecords[$value['id']]['amounts'],$sMoney,2);
            }
            if(isset($zzsRecords[$value['id']])){
                $zMoney = bcadd($zzRecords[$value['id']]['amounts'],$zMoney,2);
            }
            $value['moneys'] = bcsub(bcadd($value['initial_money'],$sMoney,2),$zMoney,2);


            if($value['tag'] == ''){
                $all_group[8]['children'][] = $value;
                $all_group[8]['money'] = bcadd($all_group[8]['money'],$value['moneys'],2);
            }else{
                $all_group[$arr_tip_str[$value['tag']]]['children'][] = $value;
                $all_group[$arr_tip_str[$value['tag']]]['money'] = bcadd($all_group[$arr_tip_str[$value['tag']]]['money'],$value['moneys'],2);
            }

        }

        $rAccount = [];
        foreach ($all_group as $value){
            if(count($value['children']) > 0){
                $rAccount[] = $value;
            }
        }
        return  self::successResponse([
            'datas'=>$rAccount,
            'money'=>bcadd(array_sum(array_column($all_group,'money')),0,2)
        ]);
    }




    public function actionSorting(){
        $tally_id = Yii::$app->getRequest()->post('tally_id');
        if(!$tally_id){
            return self::failureResponse(500,'账户Id不能为空');
        }
        $sorting = Yii::$app->getRequest()->post('sortingtype');
        $id = Yii::$app->getRequest()->post('id');

        $info = TallyAccount::find()->where([
            'tally_id'=>$tally_id,
            'id'=>$id
        ])->one();
        $sortingIndex = TallyAccount::find()->where([
            'tally_id'=>$tally_id
        ]);
        if($sorting == 1){
            $query = $sortingIndex->andFilterWhere([
                '<','sorting',$info['sorting']
            ])->orderBy('sorting DESC')->limit(1)->one();
            if($query == null){
                return  self::failureResponse(500,'无法进行调整');
            } else{
                $sortingIndex = $query['sorting'];
                $query->sorting = $info['sorting'];
                $query->save();
            }
        }else if($sorting == 2){
            $query = $sortingIndex->andFilterWhere([
                '>','sorting',$info['sorting']
            ])->orderBy('sorting ASC')->limit(1)->one();
            if($query == null){
                return  self::failureResponse(500,'无法进行调整');
            } else{
                $sortingIndex = $query['sorting'];
                $query->sorting = $info['sorting'];
                $query->save();
            }
        }


        $save = TallyAccount::find()->where([
            'tally_id'=>$tally_id,
            'id'=>$id
        ])->one();
        $save->sorting = $sortingIndex;
        if($save->save()){
            return self::successResponse();
        }


        return  self::failureResponse('500','调整失败');


    }

}
